package com.tosca.colorpicker;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class ColorPicker extends View {

    private Context context;
    private Bitmap mColorWheel = null;
    private Bitmap mWhiteWheel = null;
    private Bitmap mFramePic = null;
    private Bitmap mColorPointer = null;
    private Bitmap mPickerWheel = null;

    private Paint buttonPaint = new Paint();
    private Paint buttonBackPaint = new Paint();
    private RectF centerRectF;
    private Matrix mColorMatrix = new Matrix();
    private Matrix mWhiteMatrix = new Matrix();
    private Matrix colorPointerMatrix = new Matrix();
    private float mColorRotate = 0;
    private float mWhiteRotate = 0;
    private float preMoveRotate = 0;
    Canvas tmpCanvas = new Canvas();
    private int mBigCircle;
    private int mCenterCircle;
    private Point centerPoint;
    private float startDegrees;
    private float currentDegrees;
    private boolean isTouch = false;
    private boolean isColorTouch;
    private boolean isOn = true;
    private static int mCurrentColor;
    private OnWheelChangeListener mOnWheelChangeListener;

    public interface OnWheelChangeListener {

        void onStartTrackingTouch(ColorPicker colorPicker);

        void onStopTrackingTouch(ColorPicker colorPicker);

        void onWheelChange(boolean isColorWheel,int color);


        void onCenterClick(boolean isOn);

    }

    public ColorPicker(Context context) {
        super(context);
        this.context = context;
        init(null);
    }

    public ColorPicker(Context context , AttributeSet attrs){
        super(context, attrs);
        this.context = context;
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        TypedArray types = context.obtainStyledAttributes(attrs,
                R.styleable.color_picker);
        try {
            mBigCircle = types.getDimensionPixelOffset(
                    R.styleable.color_picker_circle_radius, 450);
        } finally {
            types.recycle(); // TypeArray用完需要recycle
        }
        mCenterCircle = mBigCircle / 2;
        Resources resources = getResources();
        mColorWheel = BitmapFactory.decodeResource(resources, R.drawable.color_wheel_whites2x);
        mFramePic = BitmapFactory.decodeResource(resources, R.drawable.edit_wheel_faceplate_white);
        mWhiteWheel = BitmapFactory.decodeResource(resources,R.drawable.edit_wheel_whites);
        mColorPointer = BitmapFactory.decodeResource(resources, R.drawable.edit_needle_color_black2x);

        centerPoint = new Point(mBigCircle, mBigCircle);

        mColorWheel = Bitmap.createScaledBitmap(mColorWheel, mBigCircle * 2, mBigCircle * 2, false);
        mWhiteWheel = Bitmap.createScaledBitmap(mWhiteWheel, mBigCircle *2, mBigCircle *2,false);
        mFramePic = Bitmap.createScaledBitmap(mFramePic, mBigCircle *2 , mBigCircle *2 , false);
        mColorPointer = Bitmap.createScaledBitmap(mColorPointer,mBigCircle/2,mBigCircle/2,false);
        mPickerWheel = Bitmap.createBitmap(mBigCircle * 2, mBigCircle * 2, mFramePic.getConfig());
        tmpCanvas.setBitmap(mPickerWheel);
        buttonPaint.setColor(Color.RED);
        buttonPaint.setStyle(Paint.Style.STROKE);
        buttonPaint.setStrokeWidth(20);
        buttonBackPaint.setColor(Color.LTGRAY);
        buttonBackPaint.setStyle(Paint.Style.FILL);
//        buttonBackPaint.setStrokeWidth(40);
        centerRectF = new RectF(mBigCircle-mCenterCircle*2/5,mBigCircle-mCenterCircle*2/5,mBigCircle+mCenterCircle*2/5,mBigCircle+mCenterCircle*2/5);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        tmpCanvas.save();
        tmpCanvas.clipRect(mBigCircle, 0, mBigCircle * 2, mBigCircle * 2);
        tmpCanvas.drawBitmap(mColorWheel, mColorMatrix, null);
        tmpCanvas.restore();
        tmpCanvas.save();
        tmpCanvas.clipRect(0, 0, mBigCircle, mBigCircle * 2);
        tmpCanvas.drawBitmap(mWhiteWheel, mWhiteMatrix, null);
        tmpCanvas.restore();
        tmpCanvas.drawBitmap(mFramePic, 0, 0, null);

        colorPointerMatrix.setRotate(-90, mColorPointer.getWidth() / 2, mColorPointer.getHeight() / 2);
        colorPointerMatrix.postTranslate(0, centerPoint.y - mColorPointer.getWidth() / 2);
        tmpCanvas.drawBitmap(mColorPointer, colorPointerMatrix, null);
        colorPointerMatrix.reset();
        colorPointerMatrix.setRotate(90, mColorPointer.getWidth() / 2, mColorPointer.getHeight() / 2);
        colorPointerMatrix.postTranslate(centerPoint.x * 2 - mColorPointer.getWidth(), centerPoint.y - mColorPointer.getHeight() / 2);
        tmpCanvas.drawBitmap(mColorPointer, colorPointerMatrix, null);
        canvas.drawBitmap(mPickerWheel, 0, 0, null);
        canvas.drawCircle(mBigCircle,mBigCircle,mCenterCircle*3/5, buttonBackPaint);
//        canvas.drawArc(centerRectF,315,270,false, buttonBackPaint);
//        canvas.drawLine(mBigCircle,mBigCircle-mCenterCircle/2,mBigCircle,mBigCircle, buttonBackPaint);
        canvas.drawArc(centerRectF,315,270,false, buttonPaint);
        canvas.drawLine(mBigCircle,mBigCircle-mCenterCircle*2/5,mBigCircle,mBigCircle, buttonPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                onStartTrackingTouch();
                if (centerTouch(event.getX(),event.getY())) {
                    isOn = !isOn;
                    if (isOn) {
                        buttonPaint.setColor(Color.RED);
                    } else {
                        buttonPaint.setColor(Color.BLACK);
                    }
                    mOnWheelChangeListener.onCenterClick(isOn);
                }
                if (!wheelTouch(event.getX(), event.getY())) {
                    isTouch = false;
                    return true;
                }
                isTouch = true;
                if (colorTouch(event.getX())) {
                    preMoveRotate = mColorRotate;
                } else {
                    preMoveRotate = mWhiteRotate;
                }
                startDegrees = getCurrentDegrees(event.getX(),event.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                updateOnTouch(event);
                break;
            case MotionEvent.ACTION_UP:
                onStopTrackingTouch();
                isTouch = false;

                break;
            case MotionEvent.ACTION_CANCEL:
                onStopTrackingTouch();
                isTouch = false;

                break;
            default:
                break;
        }
        invalidate();
        return true;
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 视图大小设置为直径
        setMeasuredDimension(mBigCircle * 2, mBigCircle * 2);
    }

    private void onStartTrackingTouch() {
        if (mOnWheelChangeListener != null) {
            mOnWheelChangeListener.onStartTrackingTouch(this);
        }
    }

    private void onStopTrackingTouch() {
        if (mOnWheelChangeListener != null) {
            mOnWheelChangeListener.onStopTrackingTouch(this);
        }
    }

    private void updateOnTouch(MotionEvent event) {
        if ( !isTouch) {
            return;
        }
        currentDegrees = getCurrentDegrees(event.getX(),event.getY());
        float moveDegrees = currentDegrees - startDegrees;
        if (isColorTouch) {
            mColorRotate = preMoveRotate + moveDegrees;
            mColorMatrix.setRotate(mColorRotate,mBigCircle,mBigCircle);
            mCurrentColor = mPickerWheel.getPixel(2*mBigCircle*7/8, mBigCircle);
            mOnWheelChangeListener.onWheelChange(isColorTouch,mCurrentColor);
//            System.out.println("mCurrentColor: " + mCurrentColor);
        }
        else {
            mWhiteRotate = preMoveRotate + moveDegrees ;
            mWhiteMatrix.setRotate(mWhiteRotate, mBigCircle, mBigCircle);
            mCurrentColor = mPickerWheel.getPixel(mBigCircle/4,mBigCircle);
            mOnWheelChangeListener.onWheelChange(isColorTouch,mCurrentColor);
        }

    }

    private boolean colorTouch(float x) {
        if (x > centerPoint.x) {
            isColorTouch = true;
        }
        else  {
            isColorTouch = false;
        }
        return isColorTouch;
    }

    private boolean wheelTouch(float x, float y) {
        boolean wheel = false;
        float touchRadius = (float) getLength(x,y,centerPoint.x,centerPoint.y);
        if ((touchRadius < mBigCircle) && (touchRadius > mCenterCircle)) {
            wheel = true;
        }
        return wheel;
    }

    private boolean centerTouch(float x, float y) {
        if ( getLength(x,y,centerPoint.x,centerPoint.y) < mCenterCircle) {
            return true;
        } else {
            return false;
        }
    }

    public static float getLength(Point a, Point b) {
        return (float) Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
    }

    public static int getLength(float x1, float y1, float x2, float y2) {
        return (int) Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
    }

    /**
     * @describe
     * @param x
     * @param y
     * @return
     */
    private float getCurrentDegrees(float x, float y) {
        float dx = x - centerPoint.x;
        float dy = y - centerPoint.y;
        float ang = (float) Math.toDegrees(Math.atan2(dy, dx));
        return ang;
    }

    public void setOnWheelChangeListener(OnWheelChangeListener l) {
        mOnWheelChangeListener = l;
    }

}
